using System;
using System.Data;
using System.Xml;
using SharpObjects.Configuration;
using SharpObjects.Configuration.ConfigurationProviders;

namespace SharpObjects.Data
{
	public class DbParameter : IDbParameter
	{
        #region CONSTRUCTORS

        public DbParameter(
			string name, 
			DbType type, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion,
			bool isNullable,
			byte precision,
			byte scale)
		{
			this.ParameterName = name;
			this.DbType = type;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = isNullable;
			this.Precision = precision;
			this.Scale = scale;
		}

		public DbParameter(
			string name, 
			string dbTypeName, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion,
			bool isNullable,
			byte precision,
			byte scale
			)
		{
			this.ParameterName = name;
		    this.DbTypeName = dbTypeName;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = isNullable;
			this.Precision = precision;
			this.Scale = scale;
		}

		public DbParameter(
			string name, 
			DbType type, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion,
			bool isNullable,
			byte precision
			)
		{
			this.ParameterName = name;
			this.DbType = type;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = isNullable;
			this.Precision = precision;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			string dbTypeName, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion,
			bool isNullable,
			byte precision
			)
		{
			this.ParameterName = name;
		    this.DbTypeName = dbTypeName;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = isNullable;
			this.Precision = precision;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			DbType type, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion,
			bool isNullable
			)
		{
			this.ParameterName = name;
			this.DbType = type;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = isNullable;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			string dbTypeName, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion,
			bool isNullable
			)
		{
			this.ParameterName = name;
		    this.DbTypeName = dbTypeName;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = isNullable;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			string dbTypeName, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion
			)
		{
			this.ParameterName = name;
		    this.DbTypeName = dbTypeName;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = true;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			DbType type, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn,
			DataRowVersion sourceRowVersion
			)
		{
			this.ParameterName = name;
			this.DbType = type;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = sourceRowVersion;
			this.IsNullable = true;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			string dbTypeName, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn
			)
		{
			this.ParameterName = name;
		    this.DbTypeName = dbTypeName;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = DataRowVersion.Current;
			this.IsNullable = true;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			DbType type, 
			ParameterDirection direction,
			int size,
			object value,
			string sourceColumn
			)
		{
			this.ParameterName = name;
			this.DbType = type;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = sourceColumn;
			this.SourceVersion = DataRowVersion.Current;
			this.IsNullable = true;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			string dbTypeName, 
			ParameterDirection direction,
			int size,
			object value
			)
		{
			this.ParameterName = name;
		    this.DbTypeName = dbTypeName;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = name;
			this.SourceVersion = DataRowVersion.Current;
			this.IsNullable = true;
			this.Precision = 0;
			this.Scale = 0;
		}

		public DbParameter(
			string name, 
			DbType type, 
			ParameterDirection direction,
			int size,
			object value
			)
		{
			this.ParameterName = name;
			this.DbType = type;
			this.Direction = direction;
			this.Size = size;
			this.Value = value;
			this.SourceColumn = name;
			this.SourceVersion = DataRowVersion.Current;
			this.IsNullable = true;
			this.Precision = 0;
			this.Scale = 0;
		}

        public DbParameter(string name, string directSqlExpression)
        {
            this.ParameterName = name;
            this.Size = 0;
            this.Value = directSqlExpression;
            this.SourceColumn = null;
            this.SourceVersion = DataRowVersion.Current;
            this.IsNullable = false;
            this.Precision = 0;
            this.Scale = 0;
            this.IsDirectSqlExpression = true;
        }
        
        public DbParameter()
		{
			this.ParameterName = null;
			this.Size = 0;
			this.Value = null;
			this.SourceColumn = null;
			this.SourceVersion = DataRowVersion.Current;
			this.IsNullable = false;
			this.Precision = 0;
			this.Scale = 0;
		}

        /*
	    <param_descriptors>
		    <param_descriptor name=":PROCESS_ID" type="Int" direction="Input" />
		    <param_descriptor name=":DESCRIPTION" type="UnicodeString" direction="Input" nullable="true" precision="0" scale="0" size="200" source_column=":DESCRIPTION" row_version="Current"/>
	    </param_descriptors>
        */
		public DbParameter(XmlElement parameterDescriptorXmlElement)
		{
			IConfigurationProvider parameter = new XmlConfigurationProvider(parameterDescriptorXmlElement);

			this.DbTypeName = parameter.GetString("@type");
			this.ParameterName = parameter.GetString("@name");
			this.Direction = MapParDirection(parameter.GetString("@direction"));	
			this.IsNullable = parameter.GetBoolean("@nullable", false);
			this.Precision = (byte)parameter.GetInteger("@precision", 0);
			this.Scale = (byte)parameter.GetInteger("@scale", 0);
			this.Size = parameter.GetInteger("@size", 0);
			this.SourceColumn = parameter.GetString("@source_column", this.ParameterName);
			this.SourceVersion = MapRowVersion(parameter.GetString("@row_version", "Current"));
		}
        
        #endregion // CONSTRUCTORS

        public static ParameterDirection MapParDirection(string direction)
        {
            ParameterDirection d = (ParameterDirection)Enum.Parse(typeof(System.Data.ParameterDirection), direction, true);
            return d;
        }

        public static DataRowVersion MapRowVersion(string rowVersion)
        {
            DataRowVersion rv = (DataRowVersion)Enum.Parse(typeof(DataRowVersion), rowVersion, true);
            return rv;
        }

		//#region IDataParameter Members

        public ParameterDirection Direction { get; set; }
        
        public DbType DbType { get; set; }

        public string DbTypeName
	    {
	        get
	        {
	            return this.DbType.ToString();
	        }
            set
            {
                this.DbType = (DbType)Enum.Parse(typeof(DbType), value, true);
            }
	    }

        public object Value { get; set; }
        public bool IsNullable { get; set; }
        public DataRowVersion SourceVersion { get; set; }
        public string ParameterName { get; set; }
        public string SourceColumn { get; set; }

		//#endregion

		//#region IDbParameter Members

        public int Size { get; set; }
        public byte Precision { get; set; }
        public byte Scale { get; set; }
        public bool IsDirectSqlExpression { get; set; }

		//#endregion

		public override string ToString()
		{
			return this.ParameterName;
		}


	}
}
